Table des matières
Installer son serveur DNS faisant autorité avec NSD
Autoriser les serveurs secondaires
Signer sa zone DNS avec OpenDNSSEC
Installer son propre DNS avec Unbound
Publié le 16/01/2020
Quand on a réservé un nom de domaine auprès d'un bureau d'enregistrement ce dernier propose souvent d'utiliser ses serveurs DNS pour faire autorité sur la zone. Mais servir sa zone avec ses propres serveurs DNS est bien plus amusant et c'est ce que nous allons faire aujourd'hui à l'aide du logiciel NSD.
Quand il s'agit d'installer un serveur DNS, que ce soit un résolveur ou un serveur faisant autorité, les yeux se tournent systématiquement vers Bind. C'est souvent un choix fait "par défaut" ou parce que c'est celui qui est enseigné en cours et qu'il fait à la fois résolveur et serveur faisant autorité. Cependant il existe bien d'autres logiciels pour servir des zones comme Knot, PowerDNS ou NSD et c'est ce dernier que j'utilise.
Dans cet article je vais prendre pour exemple la zone lithio.fr.
Pour commencer il faut dire à la zone parent qui sont les serveurs DNS faisant autorité sur notre zone en créant des Glue Records.
Parler de Glue Record dans un cours c'est en général un bon moyen de voir si les étudiant⋅e⋅s suivent. On énonce :
"Et donc la zone parent annonce que le DNS faisant autorité pour example.com est ns1.example.com"
et on voit ce qui se passe. Il y en a en général un⋅e pour dire :
"Mais si le parent dit que le DNS qui fait autorité pour example.com c'est ns1.example.com alors il faut résoudre le nom de ns1.example.com, sauf que c'est justement ns1.example.com qui a cette info !"
Et c'est vrai, c'est un problème de l'œuf et de la poule et on résout ça dans le DNS en mettant quand même dans la zone parent les enregistrement A et AAAA des serveurs DNS faisant autorité sur notre zone, en plus des enregistrements NS.
Cela se passe souvent dans l'interface du bureau d'enregistrement où on renseigne les noms et IP dans des champs Glue Record.
Nous installons NSD :
# apt install nsd
Nous modifions la configuration principale dans /etc/nsd/nsd.conf :
server:
ip-address: 198.51.200.1
ip-address: 2001:db8::1
port: 53
server-count: 1
hide-version: yes
identity: "ns1.lithio.fr"
zonesdir: "/var/lib/nsd/zones"
logfile: "/var/log/nsd.log"
pidfile: "/run/nsd/nsd.pid"
include: "/etc/nsd/nsd.conf.d/*.conf"
Cette configuration indique les adresses IP et ports sur lesquelles le serveur doit écouter, le nombre de threads ou encore le dossier qui contient les fichiers de zones.
Pour chaque zone que nous gérons nous allons créer un fichier de configuration dans /etc/nsd/nsd.conf.d/.
Nous éditons le fichier /etc/nsd/nsd.conf.d/lithio.fr.conf :
zone:
name: lithio.fr
zonefile: lithio.fr
On indique que l'on crée une zone dont le nom est lithio.fr et dont le fichier de zone se nomme aussi ainsi relativement au chemin indiqué par zonesdir dans la configuration principale de NSD.
Avoir un seul serveur DNS faisant autorité n'est vraiment pas une bonne idée car si ce dernier vient à tomber en panne ou à être inaccessible par exemple alors il devient impossible d'obtenir des réponses pour notre zone.
On fait donc attention à avoir des serveurs secondaires (Les siens, ceux d'amis, etc) qui vont se mettre à jour régulièrement en récupérant le fichier de zone auprès du serveur primaire. Pour cela il suffit de dire dans la partie zone quelles sont les IP et ports des serveurs secondaires que l'on souhaite notifier lors d'un changement dans la zone et qu'on autorise à faire du XFR.
On ajoute donc les champs notify et provide-xfr :
zone:
name: lithio.fr
zonefile: lithio.fr
notify: 198.51.100.1@53 NOKEY
provide-xfr: 198.51.100.1 NOKEY
On remarque que j'ai ajouté un NOKEY à la fin de ces lignes car il est aussi possible (et c'est recommandé) d'ajouter de l'authentification entre les primaires et les secondaires en utilisant une clé commune.
On ajoute une section key à notre configuration et on y crée une clé en précisant l'algorithme et le secret :
zone:
name: lithio.fr
zonefile: lithio.fr
notify: 198.51.100.2@53 friend_key
provide-xfr: 198.51.200.1 friend_key
key:
name: "friend_key"
algorithm: hmac-sha256
secret: "4zzNa5Hsd3qr8MBrh65xYnfOPWW+PRhQC/T5T1NDqLc="
Le secret est encodé en base64, par exemple avec cette commande :
dd if=/dev/random of=/dev/stdout count=1 bs=32 | base64
Quand on veut du coup configurer ses serveurs secondaires ou être serveur secondaire d'une zone, il faut déclarer sa zone de la même manière mais en précisant qui sont les serveurs primaires.
zone:
name: lithio.fr
zonefile: lithio.fr
allow-notify: 198.51.100.1 friend_key
request-xfr: AXFR 198.51.100.1@53 friend_key
key:
name: "friend_key"
algorithm: hmac-sha256
secret: "4zzNa5Hsd3qr8MBrh65xYnfOPWW+PRhQC/T5T1NDqLc="
Cette fois-ci avec un allow-notify pour renseigner les IP autorisées à nous notifier d'un changement dans une zone.
On oublie pas de recharger la configuration de NSD une fois modifié :
# systemctl reload nsd
Comme vu plus haut notre fichier de zone est /var/lib/nsd/zones/lithio.fr, en voici un exemple :
$ORIGIN lithio.fr.
$TTL 3600
@ IN SOA ns1.lithio.fr. contact.lithio.fr. (
2020010807 ; serial
86400 ; refresh
3600 ; retry
3600000 ; expire
3600 ; ttl
)
; NS Servers
@ IN NS ns1.lithio.fr.
@ IN NS ns2.lithio.fr.
; A Records
@ IN A 51.254.121.3
ns1 IN A 51.254.121.3
ns2 IN A 80.67.176.37
toutetrien IN A 51.254.121.3
; AAAA Records
@ IN AAAA 2001:41d0:401:3000::b8a
ns1 IN AAAA 2001:41d0:401:3000::b8a
ns2 IN AAAA 2001:910:1025:1::1
toutetrien IN AAAA 2001:41d0:401:3000::b8a
Chaque ligne (ou ensemble de ligne quand il y a des parenthèses) est un enregistrement qui s'écrit de la manière suivante :
Nom TTL Classe Type Taille Donnée
Tout cela est expliqué dans la section 3 du RFC 1035, on retrouve généralement :
•.nom : Un nom de domaine relatif au $ORIGIN de la zone ou un FQDN.
•.TTL (Time To Live) (facultatif) : La durée en seconde durant laquelle l'enregistrement devrait être conservé dans le cache d'un résolveur ("devrait" car les administrateur⋅ice⋅s de résolveurs peuvent choisir de changer cela).
•.Classe : Il en existe plusieurs mais c'est majoritairement IN pour INternet qui est utilisé (Cf. Section 3.2 du RFC 6895).
•.Type : Indique le type de l'enregistrement, il en existe plusieurs.
•.Taille (facultatif) : La taille en octets du champs Donnée.
•.Donnée : L'information que l'on souhaite associer au champ et qui dépend du Type (Du texte, une adresse IPv4 ou IPv6, un nom, etc)
Pour expliquer rapidement ce que l'on voit au début du fichier (Cf section 5 du RFC 1035) :
•.$ORIGIN : C'est le FQDN de la zone (qui nous permet d'écrire des noms relatifs à celui-ci par la suite).
•.$TTL : Le TTL par défaut s'il n'est pas précisé dans un enregistrement.
Donc pour mettre à jour notre zone DNS il nous suffit de modifier le fichier puis de dire à NSD de recharger la zone, avec la commande :
$ nsd-control reload lithio.fr
Vous avez surement remarqué que dans l'enregistrement SOA de notre zone la troisième valeur se nomme serial. Il s'agit du numéro de version de notre fichier de zone, il faut donc l'incrémenter à chaque modification du fichier.
Il ne faut surtout pas oublier de le faire sans quoi les serveurs secondaires ne voudront pas récupérer la nouvelle version de la zone.
Quant à quoi mettre comme serial, la section 2.2 du RFC 1912 recommande d'utiliser la date du jour suivie d'un nombre (YYYYMMDDnn).
On peut facilement tester que tel ou tel serveur réponde bien avec un outil comme Drill :
$ drill @ns1.lithio.fr A lithio.fr
;; ->>HEADER<<- opcode: QUERY, rcode: NOERROR, id: 38363
;; flags: qr aa rd ; QUERY: 1, ANSWER: 1, AUTHORITY: 2, ADDITIONAL: 4
;; QUESTION SECTION:
;; lithio.fr. IN A
;; ANSWER SECTION:
lithio.fr. 3600 IN A 51.254.121.3
;; AUTHORITY SECTION:
lithio.fr. 3600 IN NS ns1.lithio.fr.
lithio.fr. 3600 IN NS ns2.lithio.fr.
;; ADDITIONAL SECTION:
ns1.lithio.fr. 3600 IN A 51.254.121.3
ns2.lithio.fr. 3600 IN A 80.67.176.37
ns1.lithio.fr. 3600 IN AAAA 2001:41d0:401:3000::b8a
ns2.lithio.fr. 3600 IN AAAA 2001:910:1025:1::1
;; Query time: 21 msec
;; SERVER: 51.254.121.3
;; WHEN: Fri Jan 17 14:47:53 2020
;; MSG SIZE rcvd: 167
Au final malgré la quantité d'informations, gérer ses serveurs DNS faisant autorité est plutôt simple. La partie plus complexe arrive quand on souhaite ajouter de la sécurité avec DNSSEC (ce qu'il faut faire) mais ça fera l'objet d'un prochain article.
Publié le 19/05/2020
Aujourd'hui nous allons voir comment signer notre zone DNS avec DNSSEC, car gérer son DNS faisant autorité c'est rigolo mais y ajouter DNSSEC ça l'est aussi. DNSSEC est le protocole qui permet de sécuriser les données du DNS en signant cryptographiquement les enregistrements de zone DNS.
Je ne vais pas lister ici les bonnes raisons de signer sa zone avec DNSSEC car il existe de nombreux articles sur le sujet et en 2020 un ou une bon⋅ne adminsys sait qu'il faut signer ses zones. Il existe également de bons articles techniques (attention toutefois à bien vérifier la version d'OpenDNSSEC utilisée car les commandes, entre autres, changent entre la version 1 et 2) utiles à lire.
Si vous utilisez FreeBSD, cet article est également disponible sur https://adminblog.foucry.net/posts/info/dnssec/.
Le but de DNSSEC est que l'utilisateur final (ou plutôt son résolveur) puisse établir une chaîne de confiance entre la racine (en qui le résolveur a déjà confiance car il en connaît les clés au démarrage) et le DNS faisant autorité sur la zone lui donnant la réponse à sa requête.
En théorie le fonctionnement est le suivant :
•.Chaque zone signe ses enregistrements DNS avec une clé
•.La zone parente possède un enregistrement DNS qui contient le hash de la clé dont la zone enfant se sert pour signer
•.Comme on a confiance dans les clés de la racine, on peut vérifier toute la chaîne jusqu'aux enregistrements signés par la clé finale
Par exemple pour lithio.fr :
•.On a confiance dans les clés A de la racine et celle-ci signe ses enregistrements avec.
•.On interroge la racine qui nous dit d'aller interroger les DNS de fr.
•.La racine a aussi un enregistrement qui indique que fr signe avec une clé B
•.On interroge fr qui nous dit d'aller interroger les DNS de lithio.fr.
•.fr a aussi un enregistrement qui indique que lithio.fr signe avec une clé C.
•.On interroge lithio.fr qui nous donne notre réponse en signant avec sa clé C
Au final on a donc la racine qui signe ses réponses avec la clé A, fr qui signe ses réponses avec la clé B et lithio.fr qui signe ses réponses avec la clé C. On a de base confiance en A, A a confiance en B et B a confiance en C : ainsi on fait confiance aux réponses de lithio.fr via toute la chaîne.
Cet exemple sert juste d'explication car dans les faits chaque zone n'a pas une clé mais plusieurs : les KSK (Key Signing Keys) et les ZSK (Zone Signing Key). Les KSK sont comme les clés A, B et C de notre exemple sauf qu'au lieu de signer directement les enregistrements DNS de la zone, elles vont signer des ZSK qui, elles, vont signer les enregistrements de la zone. La chaîne de confiance suit toujours le même principe sauf qu'il y a plus d'élements. À noter que les hash de la clé fille dans la zone parente sont appelés DS (Delegation Signer).
Pour prendre un exemple concret :
Schéma DNSSEC de lithio.fr
Dans ce schéma qui représente la chaîne DNSSEC jusqu'à lithio.fr :
•.On a confiance dans la clé qui a l'id 20326 de la racine.
•.On interroge la racine qui nous dit d'aller interroger les DNS de fr.
•.La racine a bien la clé 20326 qui signe la clé 22545
•.La racine a aussi un enregistrement DS signé par 22545 qui indique que fr signe avec la clé 35095
•.On interroge fr qui nous dit d'aller interroger les DNS de lithio.fr.
•.fr a bien la clé 35095 qui signe la clé 28756
•.fr a aussi un enregistrement DS signé par 28756 qui indique que lithio.fr signe avec la clé 65035.
•.On interroge lithio.fr
•.lithio.fr a bien la clé 65035 qui signe la clé 6378
•.lithio.fr nous donne la réponse à notre requête en signant cette réponse avec la clé 6378
On peut également voir cette arborescence en utilisant drill :
$ drill -S lithio.fr SOA
;; Number of trusted keys: 2
;; Chasing: lithio.fr. SOA
DNSSEC Trust tree:
lithio.fr. (SOA)
|---lithio.fr. (DNSKEY keytag: 6378 alg: 8 flags: 256)
|---lithio.fr. (DNSKEY keytag: 65035 alg: 8 flags: 257)
|---lithio.fr. (DS keytag: 65035 digest type: 2)
|---fr. (DNSKEY keytag: 28756 alg: 8 flags: 256)
|---fr. (DNSKEY keytag: 35095 alg: 8 flags: 257)
|---fr. (DS keytag: 35095 digest type: 2)
|---. (DNSKEY keytag: 22545 alg: 8 flags: 256)
|---. (DNSKEY keytag: 20326 alg: 8 flags: 257)
;; Chase successful
Ainsi, en ayant confiance uniquement en une clé de la racine, on peut vérifier les réponses de toute la chaîne.
Dans cet article nous allons nous intéresser uniquement à la dernière partie (avec lithio.fr). Notre but va être de générer une KSK, de transmettre le DS à la zone parente pour que celle-ci puisse dire que l'on signe avec cette KSK, et d'utiliser la KSK pour signer des ZSK qui vont elles-mêmes signer les enregistrements DNS de notre zone.
Dans cet article je pars du principe que vous gérez déjà votre propre DNS faisant autorité (avec Bind ou NSD par exemple).
Dans le cadre des tests de cet article j'utilise des machines sous Debian 10 et nous allons signer la zone dnssec.lithio.fr (créée et active uniquement pour ces tests), cette zone ainsi que sa zone parente lithio.fr sont gérées par le logiciel NSD.
Nous allons donc devoir :
•.Installer les programmes utiles
•.Configurer SoftHSM (notre stockage de clés)
•.Configurer OpenDNSSEC
•.Ajouter notre zone à OpenDNSSEC
•.Publier notre zone
•.Transmettre le DS à la zone parente
•.Signer notre zone
On installe OpenDNSSEC et SoftHSM2 :
# apt install opendnssec softhsm2
OpenDNSSEC est le logiciel qui va s'occuper de la signature de la zone, la génération et la rotation des clés en suivant une politique que nous lui indiquerons. SoftHSM2 est un HSM logiciel (car nous n'avons pas de HSM matériel), SoftHSM est utilisé pour stocker des clés cryptographiques.
On crée un slot HSM sur le slot 0 avec l'étiquette (TokenLabel) OpenDNSSEC, il nous demande un code pin administrateur et utilisateur (je mets 1234 pour l'exemple mais bien sûr il faut en mettre des plus sûrs).
# softhsm2-util --init-token --slot 0 --label "OpenDNSSEC"
=== SO PIN (4-255 characters) ===
Please enter SO PIN: ****
Please reenter SO PIN: ****
=== User PIN (4-255 characters) ===
Please enter user PIN: ****
Please reenter user PIN: ****
The token has been initialized and is reassigned to slot 364027858
On peut vérifier les informations avec la commande suivante.
# softhsm2-util --show-slots
Available slots:
Slot 364027858
Slot info:
Description: SoftHSM slot ID 0x15b29fd2
Manufacturer ID: SoftHSM project
Hardware version: 2.4
Firmware version: 2.4
Token present: yes
Token info:
Manufacturer ID: SoftHSM project
Model: SoftHSM v2
Hardware version: 2.4
Firmware version: 2.4
Serial number: 6b9fa0e695b29fd2
Initialized: yes
User PIN init.: yes
Label: OpenDNSSEC
OpenDNSSEC contient 2 outils principaux qui nous intéressent : "l'enforcer" et "le signer".
L'enforcer s'occupe de faire appliquer les politiques et le signer, et bien, signe.
En éditant /etc/opendnssec/conf.xml.
On modifie le bloc du HSM pour indiquer à OpenDNSSEC où sont stockées nos clés ainsi que le pin :
<Repository name="SoftHSM">
<Module>/usr/lib/softhsm/libsofthsm2.so</Module>
<TokenLabel>OpenDNSSEC</TokenLabel>
<PIN>1234</PIN>
<SkipPublicKey/>
</Repository>
On ne touche pas à la configuration Common qui est bien comme elle est.
Les clés (surtout les ZSK) sont régulièrement changées, le logiciel en génère donc à l'avance pour assurer le remplacement de manière fluide. On va modifier la configuration de l'enforcer, pour générer nos clés 1 jour en avance.
<Enforcer>
<Datastore><SQLite>/var/lib/opendnssec/kasp.db</SQLite></Datastore>
<AutomaticKeyGenerationPeriod>P1D</AutomaticKeyGenerationPeriod>
<WorkingDirectory>/var/lib/opendnssec/enforcer</WorkingDirectory>
<WorkerThreads>2</WorkerThreads>
</Enforcer>
On va modifier la configuration du signer pour signaler - une fois la zone signée - à NSD de recharger la zone (à adapter en fonction du logiciel que vous utilisez).
<Signer>
<WorkingDirectory>/var/lib/opendnssec/signer</WorkingDirectory>
<WorkerThreads>2</WorkerThreads>
<!-- the <NotifyCommmand> will expand the following variables:
%zone the name of the zone that was signed
%zonefile the filename of the signed zone
-->
<NotifyCommand>/usr/sbin/nsd-control reload %zone</NotifyCommand>
</Signer>
On constate également qu'il n'y a pour le moment aucune clé générée :
# ods-hsmutil list
Listing keys in all repositories.
0 keys found.
Repository ID Type
---------- --
KASP pour "Key And Signature Policy" est la configuration qui contient les politiques de génération et renouvellement des clés. Le mieux pour bien en comprendre le fonctionnement est d'en lire la documentation.
On va modifier /etc/opendnssec/kasp.xml.
Nous devons ici éditer la configuration que nous allons utiliser, il y en a de base 2 : default (qui a d'ailleurs comme description A default policy that will amaze you and your friends, comme quoi on rigole bien dans le monde du DNS) et lab. Dans le cadre de ce test je vais utiliser lab, mais en production il est préférable d'en utiliser d'autres, si, par exemple, vous souhaitez signer un domaine dont la zone parente est fr, l'AFNIC à mis à disposition un document sur le sujet.
On voit également qu'on peut indiquer les algorithmes utilisés pour générer les clés, par défaut c'est le 8 (RSA-SHA256) qui est utilisé. Pour savoir quoi mettre la section 3.1 du RFC 8624 est bien utile en nous donnant un tableau qui contient les algorithmes que l'on doit, ne doit pas ou devrait employer. Je vais utiliser ici le 13 (ECDSAP256SHA256) et indique que le renouvellement de la KSK est manuel (car il faudra l'envoyer à la zone parente à la main) :
<KSK>
<Algorithm length="512">13</Algorithm>
<Lifetime>P1Y</Lifetime>
<Repository>SoftHSM</Repository>
<ManualRollover/>
</KSK>
<ZSK>
<Algorithm length="512">13</Algorithm>
<Lifetime>PT4H</Lifetime>
<Repository>SoftHSM</Repository>
</ZSK>
À noter que dans ce fichier les périodes de temps sont indiquées au format ISO 8601 (comme expliqué dans la documentation). À noter également que les valeurs sont fixes : 1Y (un an) vaudra toujours 365 jours, même les années bissextiles; 1M (un mois) vaudra toujours 31 jours, même en février.
On vérifie que notre configuration soit correcte :
# ods-kaspcheck
On initialise la base de données de l'enforcer avec la commande (on ne le fait que la première fois, plus jamais ensuite) :
# ods-enforcer-db-setup
On supprime le fichier /etc/opendnssec/prevent-startup qui empêche le lancement d'OpenDNSSEC tant que celui-ci n'est pas configuré et on lance l'enforcer et le signer DNSSEC :
# systemctl start opendnssec-enforcer
# systemctl start opendnssec-signer
On importe nos politiques :
# ods-enforcer policy import
Normalement tout est prêt pour commencer à gérer nos zones.
OpenDNSSEC prévoit de mettre les fichiers de zones dans /var/lib/opendnssec/unsigned/ et de voir le résultat signé dans /var/lib/opendnssec/signed/, dans notre cas nous avons /var/lib/opendnssec/unsigned/dnssec.lithio.fr.
Avant il fallait renseigner les zones dans le fichier /etc/opendnssec/zonelist.xml mais, comme il nous l'indique, cela a changé depuis la version 2.0 et il faut considérer la base de données de l'enforcer comme référence. Nous allons donc ajouter la zone dans la base puis exporter cette dernière dans le fichier zonelist.xml.
On ajoute notre zone à l'enforcer :
# ods-enforcer zone add --zone dnssec.lithio.fr --policy lab --input /var/lib/opendnssec/unsigned/dnssec.lithio.fr --output /var/lib/opendnssec/signed/dnssec.lithio.fr
Après chaque ajout de zone on joue la commande d'export afin de tenir le fichier zonelist.xml à jour :
# ods-enforcer zonelist export
Notre zone est normalement immédiatement signée et on peut vérifier ça dans les logs et dans le fichier de sortie.
On peut voir les clés dans notre HSM :
# ods-hsmutil list
Listing keys in all repositories.
9 keys found.
Repository ID Type
---------- -- ----
SoftHSM 1aa9234b8deeb67654e0a54073f1810f ECDSA/256
SoftHSM 4fc296406405101f2ff07d5b57dbc3f9 ECDSA/256
SoftHSM 15be78d2934f0fffdbb56cf7be69e50a ECDSA/256
SoftHSM 8b03481c104686d88c7e59d09043e776 ECDSA/256
SoftHSM b53d288301fcaf678bffb152cf13ff80 ECDSA/256
SoftHSM a755e62000e11e194c7d93a3b2c09395 ECDSA/256
SoftHSM 3f81735b5e1913ccfd0c15adafae47d9 ECDSA/256
SoftHSM 45a1dddc8e01d69c62de4a956efbd419 ECDSA/256
SoftHSM 2747f82955fea88a4495b94fc4f001be ECDSA/256
À présent il faut indiquer à notre logiciel de DNS faisant autorité sur la zone d'utiliser ce nouveau fichier contenant les signatures DNSSEC.
On vérifie ensuite que les enregistrements RRSIG soient bien présents avec dig (en demandant directement à un serveur faisant autorité sur la zone pour éviter une réponse provenant du cache du résolveur) :
$ dig @dnssec.lithio.fr +dnssec dnssec.lithio.fr
; <<>> DiG 9.11.5-P4-5.1-Debian <<>> +dnssec dnssec.lithio.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 15101
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 2, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;dnssec.lithio.fr. IN A
;; ANSWER SECTION:
dnssec.lithio.fr. 56 IN A 54.37.69.174
dnssec.lithio.fr. 56 IN RRSIG A 13 3 60 20200102143140 20200102123044 17006 dnssec.lithio.fr. CNz7ipxye839NwTm2C3xXpCisJaSWBpfgCe1ZMCakmZc0NZ+rODXPWi/ Z1E25CkuKEa86Rg/NGl3tcU56K2o0A==
On note qu'il n'y a pas le flag ad, indiquant que le résolveur n'a pas validé avec DNSSEC. C'est normal car nous demandons directement à un serveur faisant autorité, si nous demandions à un résolveur validant DNSSEC nous ne l'aurions pas non plus car la zone parente ne possède pas encore l'enregistrement DS prouvant que notre zone doit être signée.
On vérifie l'état de notre zone :
# ods-enforcer key list --verbose --all --zone dnssec.lithio.fr
Keys:
Zone: Keytype: State: Date of next transition: Size: Algorithm: CKA_ID: Repository: KeyTag:
dnssec.lithio.fr KSK publish 2020-01-02 14:40:44 512 13 2747f82955fea88a4495b94fc4f001be SoftHSM 54859
dnssec.lithio.fr ZSK ready 2020-01-02 14:40:44 512 13 1aa9234b8deeb67654e0a54073f1810f SoftHSM 17006
La KSK est en état publish, on attend qu'elle passe en état ready (on voit qu'elle attend qu'on lui indique que le DS est bien visible) :
# ods-enforcer key list --verbose --all --zone dnssec.lithio.fr
Keys:
Zone: Keytype: State: Date of next transition: Size: Algorithm: CKA_ID: Repository: KeyTag:
dnssec.lithio.fr KSK ready waiting for ds-seen 512 13 2747f82955fea88a4495b94fc4f001be SoftHSM 54859
dnssec.lithio.fr ZSK active 2020-01-02 18:30:44 512 13 1aa9234b8deeb67654e0a54073f1810f SoftHSM 17006
On exporte alors son DS :
# ods-enforcer key export --zone dnssec.lithio.fr --ds
;ready KSK DS record (SHA256):
dnssec.lithio.fr. 3600 IN DS 54859 13 2 b0f3c176f7f8d5a8712f87582b462d4e7f7450da7a8f24e2f2bb71c0fc212356
On le transmet à la zone parente. Dans mon cas je l'ajoute à la zone lithio.fr mais sinon, il faut en général le transmettre via votre bureau d'enregistrement, qui doit avoir un formulaire pour cela.
Une fois le temps de juvénisation passé, on indique à l'enforcer que l'enregistrement DS à été "vu" et que l'on peut signer avec en précisant la KSK en question (son keytag) :
# ods-enforcer key ds-seen --zone dnssec.lithio.fr --keytag 54859
1 KSK matches found.
1 KSKs changed.
On constate que notre KSK est à présent active :
# ods-enforcer key list -v --all --zone dnssec.lithio.fr
Keys:
Zone: Keytype: State: Date of next transition: Size: Algorithm: CKA_ID: Repository: KeyTag:
dnssec.lithio.fr KSK active 2020-01-02 18:30:44 512 13 2747f82955fea88a4495b94fc4f001be SoftHSM 54859
dnssec.lithio.fr ZSK active 2020-01-02 18:30:44 512 13 1aa9234b8deeb67654e0a54073f1810f SoftHSM 17006
On vérifie avec dig, normalement notre zone est à présent signée et le flag ad présent (attention à ce que le résolveur utilisé ne transmette pas une réponse du cache) :
$ dig +dnssec dnssec.lithio.fr
; <<>> DiG 9.11.5-P4-5.1-Debian <<>> +dnssec dnssec.lithio.fr
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 3212
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags: do; udp: 4096
;; QUESTION SECTION:
;dnssec.lithio.fr. IN A
;; ANSWER SECTION:
dnssec.lithio.fr. 60 IN A 54.37.69.174
dnssec.lithio.fr. 60 IN RRSIG A 13 3 60 20200102143140 20200102123044 17006 dnssec.lithio.fr. CNz7ipxye839NwTm2C3xXpCisJaSWBpfgCe1ZMCakmZc0NZ+rODXPWi/ Z1E25CkuKEa86Rg/NGl3tcU56K2o0A==
On peut utiliser des outils comme dnsviz ou drill pour vérifier que tout marche bien.
Il convient bien sûr de surveiller nos signatures DNSSEC afin de voir si un souci arrive, pour cela on peut consulter la section 3.5 du document de l'AFNIC.
Stéphane Bortzmeyer a également fait un article sur le sujet avec Icinga.
Il existe d'autres solutions mais ce n'est pas l'objet de cet article.
Maintenant que notre zone DNS est signée, on peut avoir une confiance raisonnable dans les informations qui s'y trouvent (si on utilise un résolveur validant bien sûr), ce qui n'était pas forcement le cas avant.
Les KSK rollover et changements d'algorithmes feront peut-être l'objet d'un futur article (oui c'est risqué de dire ça je sais).
Merci à Jacques Foucry, Imriel, Stéphane Bortzmeyer et Baptiste Dauphin pour leur relecture et avis.
Un DNS (Domain Name Server) faisant authorité est comme son nom l'indique un serveur de noms de domaine : sur internet chaque machine est identifiée par son adresse IP, or il est difficile pour un être humain de retenir des adresses comme 88.191.250.176 et ceci pour chaque site web (à moins que vous ne soyez une base de données ambulante).
Les DNS font donc entre autres correspondre les noms de domaines aux adresses IP correspondantes.
Par exemple : linuxfr.org => 88.191.250.176
La plupart des gens utilisent les résolveurs DNS de leur fournisseur d'accès internet, cependant ces DNS sont souvent dit « menteurs », c'est à dire qu'ils ne renvoient pas la vrai adresse de certains sites (pour des raisons de censure dans le pays, …). Il est donc important d'avoir un DNS non-menteur afin de pouvoir naviguer librement, de plus les résolveurs de certains FAI peuvent souvent êtes plus lent que d'autres.
Quelles solutions à cela ?
1- Utiliser des DNS publiques comme ceux de OpenDNS ou Google
2- Installer son propre résolveur DNS
Mais comme Google connaît déjà assez de choses sur nous et que l'on aime la bidouille on va installer notre propre serveur. On se connecte à notre serveur, Raspberry, ordinateur personnelle ou autre machine Linux… et en root pour l'aventure !
Installer Unbound :
# apt-get install unbound
Récupérer la configuration des DNS racine :
# wget https://ftp.internic.net/domain/named.cache -O /var/lib/unbound/root.hints
Fichier de configuration de Unbound : /etc/unbound/unbound.conf
# Unbound configuration file for Debian.
server:
# Configuration de unbound pour DNSSEC
# en utilisant la clé des serveurs root
auto-trust-anchor-file: "/var/lib/unbound/root.key"
# Activer les logs
verbosity: 1
#Répondre aux requêtes DNS sur toutes les interfaces réseau.
interface: <votre-ipv4-ici>
interface: <votre-ipv6-ici>
#Port requêtes DNS
port: 53
#Activation de l'IPv4
do-ip4: yes
#Activation de l'IPv6
do-ip6: yes
# Activation udp
do-udp: yes
#Activation tcp
do-tcp: yes
#plages adresse ip autorisée à utiliser le DNS (mettez votre réseau)
access-control: 192.168.1.0/24 allow
#chemin du fichier root.hints avec les infos sur les DNS racine
root-hints: "/var/lib/unbound/root.hints"
#Cacher les infos sur le serveur DNS
hide-identity: yes
hide-version: yes
#paramètre limitant l'usurpation de DNS
harden-glue: yes
#Requérir les infos DNSSEC pour les zones de confiance
harden-dnssec-stripped: yes
#Options permettant de ne pas prendre la casse en compte lors des requêtes d'url.
use-caps-for-id: yes
#valeur mini de la TTL en secondes. Ne pas dépasser 1h
cache-min-ttl: 3600
#valeur max de la TTL en secondes.
cache-max-ttl: 86400
#activation du prefetch. Si un requête est faite lorsque la tll expire dans moins de 10% du temps qu'il lui est imparti
#le cache se mettra à jour aussitôt après avoir répondu à la requête.
prefetch: yes
#nombre de threads du DNS
num-threads: 1
# Tweaks et optimisations du cache
#Nombre de slabs à utiliser . Doit être une puissance de 2 du num-threads.
msg-cache-slabs: 8
rrset-cache-slabs: 8
infra-cache-slabs: 8
key-cache-slabs: 8
#Taille du cache en Mo:
rrset-cache-size: 51m
msg-cache-size: 25m
#Taille du buffer pour le port UPD en entrée. Evite la perte de message lors des requêtes
so-rcvbuf: 1m
#Renforcer la vie privée des adresses du LAN. Ne mettre que des adresses locales
private-address: 192.168.1.0/24
private-address: <votre-subnet-ipv6-ici>
#Si non nulles, les réponses indésirables ne sont pas seulement signalés dans les statistiques,
#mais aussi ajoutées à un total cumulé maintenu par thread.
#Si elle atteint le seuil, un avertissement est affiché et une action défensive est prise, le cache est vidé pour éviter l'empoissonnement DNS.
#Une valeur de 10000 est suggérée, la valeur par défaut est de 0 (service désactivé).
unwanted-reply-threshold: 10000
#Autorisé à répondre aux requêtes de localhost
do-not-query-localhost: no
# Est-ce que cette section supplémentaire doit être conservée intacte pour les données non-sécurisées
# Utile pour protéger les utilisateurs d'une validation de données potentiellement boguées
# Toutes les données non signés dans la section supplémentaire seront retirés des messages sécurisés
val-clean-additional: yes
On redémarre notre DNS :
# service unbound restart
Et vous voilà avec votre petit DNS fonctionnel, vous pourrez ainsi sûrement diminuer votre temps de réponse lors des requêtes DNS et ne pas subir les aléas politiques.